{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [Java 程序员都需要懂的 反射！](https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247486658&idx=1&sn=58e682f3b9c68def4f12c574afac0de3&chksm=ebd74dc3dca0c4d542aa7ef2f7944dba438a447ffc2b39650dc4362698c6a7acd32e1a5fe3dc&token=2140209384&lang=zh_CN#rd)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 序言\n",
    "在学习Java基础的时候，一般都会学过反射。我在初学反射的时候，并不能理解反射是用来干嘛的。学了一些API发现：“明明我自己能直接new一个对象，为什么它要绕一个圈子，先拿到Class对象，再调用Class对象的方法来创建对象呢，这不是多余吗？”"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 引出Class对象\n",
    "首先我们来看一段代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-26T19:27+0000",
     "start_time": "2020-08-26T19:27:39.676Z"
    }
   },
   "outputs": [],
   "source": [
    "public class Demo {\n",
    "    // 自建了一个Student类\n",
    "    class Student{\n",
    "    }\n",
    "    public static void main() {\n",
    "        // 将Object 强转成Student类\n",
    "        Object o = new Object();\n",
    "        Student s = (Student) o;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-26T19:27+0000",
     "start_time": "2020-08-26T19:27:19.322Z"
    }
   },
   "outputs": [
    {
     "ename": "EvalException",
     "evalue": "class java.lang.Object cannot be cast to class REPL.$JShell$12$Demo$Student (java.lang.Object is in module java.base of loader 'bootstrap'; REPL.$JShell$12$Demo$Student is in unnamed module of loader jdk.jshell.execution.DefaultLoaderDelegate$RemoteClassLoader @646007f4)",
     "output_type": "error",
     "traceback": [
      "\u001b[1m\u001b[31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1m\u001b[31mjava.lang.ClassCastException: class java.lang.Object cannot be cast to class REPL.$JShell$12$Demo$Student (java.lang.Object is in module java.base of loader 'bootstrap'; REPL.$JShell$12$Demo$Student is in unnamed module of loader jdk.jshell.execution.DefaultLoaderDelegate$RemoteClassLoader @646007f4)\u001b[0m",
      "\u001b[1m\u001b[31m\tat Demo.main(#12:8)\u001b[0m",
      "\u001b[1m\u001b[31m\tat .(#25:1)\u001b[0m"
     ]
    }
   ],
   "source": [
    "Demo.main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "编译成功，运行失败。\n",
    "- 强转失败了"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "那么“Java”（实质上JVM）是怎么知道我们写的**强转**有没有问题的呢？可以依赖**Class**对象来协助判断。\n",
    "\n",
    "- 一个`.java`的文件经过`javac`命令编译成功后，得到一个`.class`的文件\n",
    "- 当我们执行了初始化操作(有可能是new、有可能是子类初始化 父类也一同被初始化、也有可能是反射…等)，会将`.class`文件通过**类加载器**装载到`jvm`中\n",
    "- 将`.class`文件加载器加载到jvm中，又分了好几个步骤，其中包括 `加载、连接和初始化`\n",
    "- 其中在加载的时候，会在Java堆中创建一个`java.lang.Class`类的对象，这个Class对象代表着**类相关的信息**。\n",
    "\n",
    "既然说，Class对象代表着类相关的信息，那说明只要类有什么东西，在Class对象我都能找得到。\n",
    "\n",
    "于是我们**可以通过Class对象来判断对象的真正类型**。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 反射介绍\n",
    "其实反射就是围绕着`Clas`s对象和`java.lang.reflect`类库来学习，就是各种的API\n",
    "\n",
    "`Method/Field/Constructor`这些都是在`java.lang.reflect`类库下\n",
    "\n",
    "**笔记**\n",
    "```\n",
    "想要使用反射，先要得到class文件对象，其实也就是得到Class类的对象\n",
    "Class类主要API：\n",
    "        成员变量  - Field\n",
    "        成员方法  - Constructor\n",
    "        构造方法  - Method\n",
    "获取class文件对象的方式：\n",
    "        1：Object类的getClass()方法\n",
    "        2：数据类型的静态属性class\n",
    "        3：Class类中的静态方法：public static Class ForName(String className)\n",
    "--------------------------------  \n",
    "获取成员变量并使用\n",
    "        1: 获取Class对象\n",
    "        2：通过Class对象获取Constructor对象\n",
    "        3：Object obj = Constructor.newInstance()创建对象\n",
    "        4：Field field = Class.getField(\"指定变量名\")获取单个成员变量对象\n",
    "        5：field.set(obj,\"\") 为obj对象的field字段赋值\n",
    "如果需要访问私有或者默认修饰的成员变量\n",
    "        1:Class.getDeclaredField()获取该成员变量对象\n",
    "        2:setAccessible() 暴力访问  \n",
    "---------------------------------          \n",
    "通过反射调用成员方法\n",
    "        1：获取Class对象\n",
    "        2：通过Class对象获取Constructor对象\n",
    "        3：Constructor.newInstance()创建对象\n",
    "        4：通过Class对象获取Method对象  ------getMethod(\"方法名\");\n",
    "        5: Method对象调用invoke方法实现功能\n",
    "如果调用的是私有方法那么需要暴力访问\n",
    "        1: getDeclaredMethod()\n",
    "        2: setAccessiable();          \n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 为什么需要反射\n",
    "主要有两个原因：\n",
    "- 提高程序的灵活性\n",
    "- 屏蔽掉实现的细节，让使用者更加方便好用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 案例一（JDBC）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T09:44+0000",
     "start_time": "2020-08-27T09:44:38.829Z"
    }
   },
   "outputs": [
    {
     "ename": "EvalException",
     "evalue": "com.mysql.jdbc.Driver",
     "output_type": "error",
     "traceback": [
      "\u001b[1m\u001b[31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1m\u001b[31mjava.lang.ClassNotFoundException: com.mysql.jdbc.Driver\u001b[0m",
      "\u001b[1m\u001b[31m\tat java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)\u001b[0m",
      "\u001b[1m\u001b[31m\tat jdk.jshell/jdk.jshell.execution.DefaultLoaderDelegate$RemoteClassLoader.findClass(DefaultLoaderDelegate.java:154)\u001b[0m",
      "\u001b[1m\u001b[31m\tat java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)\u001b[0m",
      "\u001b[1m\u001b[31m\tat java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)\u001b[0m",
      "\u001b[1m\u001b[31m\tat java.base/java.lang.Class.forName0(Native Method)\u001b[0m",
      "\u001b[1m\u001b[31m\tat java.base/java.lang.Class.forName(Class.java:315)\u001b[0m",
      "\u001b[1m\u001b[31m\tat .(#26:1)\u001b[0m"
     ]
    }
   ],
   "source": [
    "Class.forName(\"com.mysql.jdbc.Driver\");\n",
    "\n",
    "//获取与数据库连接的对象-Connetcion\n",
    "connection = DriverManager.getConnection(\"jdbc:mysql://localhost:3306/java3y\", \"root\", \"root\");\n",
    "\n",
    "//获取执行sql语句的statement对象\n",
    "statement = connection.createStatement();\n",
    "\n",
    "//执行sql语句,拿到结果集\n",
    "resultSet = statement.executeQuery(\"SELECT * FROM users\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Java",
   "language": "java",
   "name": "java"
  },
  "language_info": {
   "codemirror_mode": "java",
   "file_extension": ".jshell",
   "mimetype": "text/x-java-source",
   "name": "Java",
   "pygments_lexer": "java",
   "version": "11.0.8+10-post-Ubuntu-0ubuntu120.04"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
